import Data.List (transpose)
import Utils (firstRecElem)
import Data.Maybe (fromJust)

moveLeft :: String -> String
moveLeft [] = []
moveLeft s@(c:cs)
    | c == 'O' = 'O' : moveLeft cs
    | c == '#' = '#' : moveLeft cs
    | c == '.' = (replicate nbO 'O') ++ (replicate nbOots '.') ++ moveLeft s'
    where
        nbO    = length . filter (=='O') . takeWhile (/='#') $ s
        nbOots = length . filter (=='.') . takeWhile (/='#') $ s
        s'     = dropWhile (/='#') s

laod :: [String] -> Int
load = sum
     . map (\(i, s) -> (*i) . length . filter (=='O') $ s)
     . zip [1..]
     . reverse

{-
    [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ]

    [
        [1, 4, 7],
        [2, 5, 8],
        [3, 6, 9],
    ]

    [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ]
-}

tiltNorth :: [String] -> [String]
tiltNorth = transpose . map moveLeft . transpose

spin :: [String] -> [String]
spin = 
    tiltEast . tiltSouth . tiltWest . tiltNorth
    where
        tiltWest  = map moveLeft
        tiltEast  = map (reverse . moveLeft . reverse)
        tiltSouth = transpose . tiltEast . transpose

main = do
    contents <- readFile "input.txt"
    let grid = lines $ contents

    print $ load . tiltNorth $ grid

    let steps    = iterate spin grid
    let (i1, i2) = fromJust . firstRecElem $ steps
    let i = i1 + (1_000_000_000 - i1) `rem` (i2 - i1)
    print $ load $ (steps !! i)